/*
 * @Author: zk
 * @Date: 2021-06-02 17:14:50
 * @LastEditTime: 2021-07-15 14:54:53
 */
#ifndef __CONTAINER_H_
#define __CONTAINER_H_

#include "stddef.h"
#include "string.h"

extern void *__POINTER_SIZE__;
#define getPointerSize(TYPE) ((unsigned long)((TYPE)__POINTER_SIZE__ + 1) - (unsigned long)((TYPE)__POINTER_SIZE__))
#define MOD(x, y) ((x < 0 ? x + y : x) % y)

typedef struct rb_node
{
    unsigned long rb_parent_color;
    struct rb_node *rb_right;
    struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long)))) Node;

typedef struct
{
    Node node;
    char *key;
    char *val;
} Pair;

typedef struct rb_root
{
    Node *rb_node;
    int length;
    int size;
    void *(*get)(struct rb_root *root, char *key);
    int (*set)(struct rb_root *root, char *key, void *val);
    int (*remove)(struct rb_root *tree, char *key);
    void *(*keys)(struct rb_root *tree, void *key);
    void *(*values)(struct rb_root *tree, void *val);
    void (*clear)(struct rb_root *tree);
} Map;

void *map_get(Map *root, char *key);
int map_set(Map *root, char *key, void *val);
int map_remove(Map *tree, char *key);
void *map_keys(Map *tree, void *key);
void *map_values(Map *tree, void *val);
void map_clear(Map *tree);

#define newMap(TYPE)          \
    {                         \
        .rb_node = NULL,      \
        .length = 0,          \
        .size = sizeof(TYPE), \
        .get = map_get,       \
        .set = map_set,       \
        .remove = map_remove, \
        .keys = map_keys,     \
        .values = map_values, \
        .clear = map_clear    \
    }

typedef struct
{
    // Initialization information.
    const int capacity;
    const int size;

    int head;
    int tail;
    int length;
    int current;

    // Method.
    int (*full)(void *deque);
    int (*empty)(void *deque);
    int (*lpush)(void *deque, ...);
    int (*rpush)(void *deque, ...);
    int (*flpush)(void *deque, ...);
    int (*frpush)(void *deque, ...);
    void *(*lpop)(void *deque, void *data);
    void *(*rpop)(void *deque, void *data);
    void *(*get)(void *deque, int index);
    void (*clear)(void *deque);
    void *(*next)(void *deque);
    void *(*previous)(void *deque);

    char *data;
} Deque;

int deque_full(void *deque);
int deque_empty(void *deque);
int deque_lpush(void *deque, ...);
int deque_flpush(void *deque, ...);
int deque_rpush(void *deque, ...);
int deque_frpush(void *deque, ...);
void *deque_lpop(void *deque, void *data);
void *deque_rpop(void *deque, void *data);
void *deque_get(void *deque, int index);
void deque_clear(void *deque);
void *deque_next(void *deque);
void *deque_previous(void *deque);

#define newDeque(TYPE, CAPACITY)    \
    {                               \
        .size = sizeof(TYPE),       \
        .capacity = CAPACITY,       \
        .head = 0,                  \
        .tail = 0,                  \
        .current = 0,               \
        .full = deque_full,         \
        .empty = deque_empty,       \
        .lpush = deque_lpush,       \
        .rpush = deque_rpush,       \
        .flpush = deque_flpush,     \
        .frpush = deque_frpush,     \
        .lpop = deque_lpop,         \
        .rpop = deque_rpop,         \
        .get = deque_get,           \
        .clear = deque_clear,       \
        .next = deque_next,         \
        .previous = deque_previous, \
        .data = NULL                \
    }

typedef struct ZSET_NODE
{
    int score;
    struct ZSET_NODE *previous;
    struct ZSET_NODE *next;
    char data[];
} ZNode;

typedef struct
{
    // 0(default) for ascending and 1 for descending
    const int reverse;
    const int size;

    ZNode *head;
    ZNode *tail;
    ZNode *current;
    int length;

    int (*add)(void *zset, int score, ...);
    void *(*pop)(void *zset, int index, void *data);

    void *(*get)(void *zset, int index);
    void *(*find)(void *zset, int score);
    void (*set)(void *zset, int index, int score);

    void (*clear)(void *zset);

    void *(*next)(void *zset);
    void *(*previous)(void *zset);

    void (*delete)(void *zset, int index);
    void *(*remove)(void *zset, int score, void *data);
} Zset;

int zset_add(void *zset, int score, ...);
void *zset_pop(void *zset, int index, void *data);
void *zset_get(void *zset, int index);
void *zset_find(void *zset, int score);
void zset_set(void *zset, int index, int score);
void zset_clear(void *zset);
void *zset_next(void *zset);
void *zset_previous(void *zset);
void zset_delete(void *zset, int index);
void *zset_remove(void *zset, int score, void *data);

#define newZset(TYPE)         \
    {                         \
        .size = sizeof(TYPE), \
        .reverse = 0,         \
        .head = NULL,         \
        .tail = NULL,         \
        .current = NULL,      \
        .length = 0,          \
        zset_add,             \
        zset_pop,             \
        zset_get,             \
        zset_find,            \
        zset_set,             \
        zset_clear,           \
        zset_next,            \
        zset_previous,        \
        zset_delete,          \
        zset_remove           \
    }

#endif
